package com.heima.admin.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.client.ArticleFeign;
import com.heima.client.WemediaFeign;
import com.heima.common.exception.CustException;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.SensitiveWordUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;


import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {

    @Autowired
    WemediaFeign wemediaFeign;

    @Value("${file.oss.web-site}")
    String webSite;

    /**
     * 自媒体文章审核!
     *
     * @param wmNewsId 自媒体文章 ID
     */
    @Override
    public void autoScanByMediaNewsId(Integer wmNewsId) {
        // 根据自媒体文章调用其他服务查询文章详细信息
        ResponseResult<WmNews> byId = wemediaFeign.findById(wmNewsId);
        if (byId.getCode().intValue() != 0) {
            // get Erroemessage 错误信息
            log.error("远程获自媒体信息失败 文章id:{}   原因:{}", wmNewsId, byId.getErrorMessage());
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR, "远程获自媒体信息失败");
        }
        WmNews wmNewsData = byId.getData();
        if (wmNewsData == null) {
            log.error("未获取到文章信息 文章id:{}  原因:{}", wmNewsId, byId.getErrorMessage());
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "未获取到文章信息");
        }
        Short status = wmNewsData.getStatus();
        // 判断文章状态, if是4/8 并且发布时间小于等于当前时间
        if (status == 4 || status == 8 && wmNewsData.getPublishTime().getTime() <= System.currentTimeMillis()) {
            // 条件满足,--> 发布
            publishArticle(wmNewsData);
            return;
        }

        //判断状态是否为 1(待审核), 进行审核
        if (status == WmNews.Status.SUBMIT.getCode()) {

            // Todo: 抽取文章内容和图片内容(url)
            Map<String, Object> textAndImagesResult = handleTextAndImages(wmNewsData);

            // Todo: 使用 DFA算法审核内容(敏感词) 不通过 : 2
            // 取出敏感词
            boolean sensitiveScan = handleSensitive((String) textAndImagesResult.get("content"), wmNewsData);
            if (!sensitiveScan) {
                // true 通过  false 不通过
                return;
            }

            // Todo: 阿里云文本内容审核 不通过--> 2  转人工审--> 3
            boolean textScan = handleTextScan((String) textAndImagesResult.get("content"), wmNewsData);
            if (!textScan) {
                return;
            }
            // Todo: 阿里云图片审核 不通过--> 2  转人工审--> 3
            List images = (List<String>)textAndImagesResult.get("images");
            if (images.size() > 0 && images != null) {
                boolean imageScan = handleImageScan(images,wmNewsData);
                if (!imageScan) {
                    return;
                }
            }
            // 以上审核全部通过情况下:

            // 判断发布时间是否小于当前时间 修改文章状态 --> 8 (审核通过)

            updateWmNews(wmNewsData, (short)8,"审核通过");
        }

//
//        if (wmNewsData.getPublishTime().getTime() < System.currentTimeMillis() &&  ) {
//            // 满足:发布
//            publishArticle(wmNewsData);
//        }


    }


    @Autowired
    ArticleFeign articleFeign;
    /**
     * 文章发布
     * @param wmNewsData
     */
    private void publishArticle(WmNews wmNewsData) {
        System.out.println("文章发布方法执行.....");
        // Todo: 远程调用saveArticl 保存三张数据表的信息
        ResponseResult responseResult = saveArticle(wmNewsData);
        if (responseResult.getCode().intValue() != 0) {
            log.error("远程保存apArticle信息失败: {}", responseResult.getErrorMessage());
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR,"远程保存apArticle信息失败");
        }
        // Todo: 修改自媒体文章状态 9
        wmNewsData.setArticleId((long) responseResult.getData());
        updateWmNews(wmNewsData, (short) 9, "发布成功");


        // Todo: 通知 ES 索引库添加对应文章

        System.out.println("发布文章");
    }

    @Autowired
    AdChannelMapper adChannelMapper;
    /**
     * 远程调用feign保存三张表信息
     * @param wmNewsData
     * @return
     */
    private ResponseResult saveArticle(WmNews wmNewsData) {
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNewsData, articleDto);
        // 如果之前没有发布过 id为 null 如果发布过为之前关联的 articleid
        articleDto.setId(wmNewsData.getArticleId());
        articleDto.setLayout(wmNewsData.getType());

        if (wmNewsData.getChannelId() != null) {
            AdChannel adChannel = adChannelMapper.selectById(wmNewsData.getChannelId());
            articleDto.setChannelName(adChannel.getName());
        }
        articleDto.setFlag((byte) 0);
        articleDto.setWmUserId(wmNewsData.getUserId());

        return articleFeign.saveArticle(articleDto);

    }

    @Autowired
    GreenImageScan greenImageScan;
    /**
     * 阿里云图片审核
     * @param images
     * @param wmNewsData
     * @return
     */
    private boolean handleImageScan(List images, WmNews wmNewsData) {
        boolean flag = true;
        try {
            Map map = greenImageScan.imageUrlScan(images);
            String suggestion = (String) map.get("suggestion");
            if ("review".equals(suggestion)) {
                flag = false;
                updateWmNews(wmNewsData, (short) 3, "图片中有不确定的内容转为人工处理");
            }
            if ("block".equals(suggestion)) {
                flag = false;
                updateWmNews(wmNewsData, (short) 2, "图片违规转为人工处理");
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
            updateWmNews(wmNewsData, (short)3,"阿里云图片审核调用失败,转为人工处理!");
        }
        return flag;
    }

    @Autowired
    GreenTextScan greenTextScan;
    /**
     * 阿里云文本审核
     * @param content
     * @param wmNewsData
     * @return
     */
    private boolean handleTextScan(String content, WmNews wmNewsData) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String) map.get("suggestion");
            if ("review".equals(suggestion)) {
                flag = false;
                updateWmNews(wmNewsData, (short) 3, "文本中有不确定的内容转为人工处理");
            }
            if ("block".equals(suggestion)) {
                flag = false;
                updateWmNews(wmNewsData, (short) 2, "文本中有违规词汇转为人工处理");
            }

        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
            updateWmNews(wmNewsData, (short)3,"阿里云文本调用失败,转为人工处理!");
        }

        return flag;


    }

    @Autowired
    AdSensitiveMapper adSensitiveMapper;

    /**
     * DFA 敏感词审核
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleSensitive(String content, WmNews wmNews) {
        boolean flag = true;
        // 查询敏感词
        List<String> allBySensitives = adSensitiveMapper.findAllBySensitives();
        // 封装 DFA 数据模型
        SensitiveWordUtil.initMap(allBySensitives);
        // 基于DFA 敏感词检测
        Map<String, Integer> stringIntegerMap = SensitiveWordUtil.matchWords(content);
        if (stringIntegerMap != null && stringIntegerMap.size() > 0) {
            // 包含敏感词
            flag = false;
            // 修改文章状态  改为 2
            updateWmNews(wmNews, (short) 2, "内容存在敏感词:" + stringIntegerMap);
        }

        return flag;
    }

    /**
     * 修改文章状态
     *
     * @param wmNews 文章
     * @param status 状态
     * @param reson  原因
     */
    private void updateWmNews(WmNews wmNews, short status, String reson) {

        wmNews.setStatus(status);
        wmNews.setReason(reson);
        ResponseResult responseResult = wemediaFeign.updateWmNews(wmNews);
        if (responseResult.getCode().intValue() != 0) {
            log.error("远程调用wmmediaFeign修改WMnews失败 :{}", responseResult.getErrorMessage());
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR, "远程调用wmmediaFeign修改WMnews失败");
        }
    }


    /**
     * 抽取文章中的文本内容和图片url
     *
     * @param wmNewsData 文章
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNewsData) {
        //  文章内容转化,  List<map>
        List<Map> contentMap = JSONArray.parseArray(wmNewsData.getContent(), Map.class);
        // 抽取 文本  标题-->内容
        StringBuilder stringBuilder = new StringBuilder(wmNewsData.getTitle() + "O(∩_∩)O");
        String content = contentMap.stream().filter(x -> "text".equals(x.get("type")))
                .map(x -> (String) x.get("value"))
                .collect(Collectors.joining("(●ˇ∀ˇ●)"));
        // 拼接集合文本内容
        stringBuilder.append(content);

        // 图片抽取
        // 内容图片
        List<String> images = contentMap.stream().filter(x -> "image".equals(x.get("type")))
                .map(x -> (String) x.get("value"))
                .collect(Collectors.toList());
        // 封面图片
        if (StringUtils.isNotBlank(wmNewsData.getImages())) {
            // 封面不为空 获取url 没有前缀,多个用 , 分割
            String[] split = wmNewsData.getImages().split(",");
            List<String> coverUrls = Arrays.stream(split).map(url -> webSite + url)
                    .collect(Collectors.toList());

            // 合并集合
            images.addAll(coverUrls);
        }
        // 去除封面内容重复图片
        images = images.stream().distinct().collect(Collectors.toList());

        Map result = new HashMap();
        result.put("content", stringBuilder.toString());
        result.put("images", images);

        return result;
    }
}
